package code.Najib;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.StringTokenizer;

import client.domainModels.Node.Node;
import client.domainModels.NodeImpl.LogFile;

public class ActivityAgentNetDiscovery {

	public static ArrayList<String> agents = new ArrayList<String>();
	public static ArrayList<String> tasks = new ArrayList<String>();
	private static ArrayList<String> EXECUTE = new ArrayList<String>() {
		{
			add("execute");
		};
	};

	public static void getActivityAgentNet(LogFile log) {
		int agentAmount = getAgentAmount(log);

		agents = new ArrayList<String>();
		int amountAgent = getAgentAmount(log);
		Integer[][] activityAgentNetMatrix = getActivityAgentNetMatrix(log);

		Integer[][] netDrawMatrix = new Integer[amountAgent][amountAgent];
		for (int i = 0; i < amountAgent; i++) {
			for (int j = 0; j < amountAgent; j++) {
				netDrawMatrix[i][j] = 0;
			}
		}

		/**************************************/
		activityAgentNetMatrix[7][0] = 1;
		activityAgentNetMatrix[5][1] = 1;
		activityAgentNetMatrix[2][2] = 1;
		activityAgentNetMatrix[0][3] = 1;
		activityAgentNetMatrix[1][4] = 1;
		activityAgentNetMatrix[3][5] = 1;
		activityAgentNetMatrix[4][6] = 1;
		for (int i = 0; i < agents.size(); i++) {
			for (int j = 0; j < tasks.size(); j++) {
				System.out.print(activityAgentNetMatrix[i][j] + "  ");
			}
			System.out.println();
		}
		/**************************************/
		// analyse the matrix
		for (int j = 0; j < tasks.size(); j++) {
			for (int i = 0; i < agents.size(); i++) {
				if (activityAgentNetMatrix[i][j] == 0)
					continue;
				for (int ii = agents.size() - 1; ii > i; ii--) {
					if (activityAgentNetMatrix[ii][j] == 0)
						continue;
					else {
						netDrawMatrix[i][ii] = 1;
						netDrawMatrix[ii][i] = 1;
					}
				}
			}
		}

		/* Test************* */
		System.out.println("Final");
		for (int i = 0; i < agents.size(); i++) {
			for (int j = 0; j < agents.size(); j++) {
				System.out.print(netDrawMatrix[i][j] + "  ");
			}
			System.out.println();
		}
		createFileVNA(netDrawMatrix, "./same_activity.vna");
		createBatchFile("./batch.txt","same_activity.vna");
	}

	public static Integer[][] getActivityAgentNetMatrix(LogFile log) {

		int agentAmount = getAgentAmount(log);
		int taskAmount = getTaskAmount(log);

		Integer[][] activityAgentNetMatrix = new Integer[agentAmount][taskAmount];

		// initiail
		for (int i = 0; i < agentAmount; i++) {
			for (int j = 0; j < taskAmount; j++) {
				activityAgentNetMatrix[i][j] = 0;
			}
		}

		String[] nodes = log.getChildNodeNames();
		// Get leaves nodes of root node.
		for (int i = 0; i < nodes.length; i++) {
			// name of root node's leaves nodes.
			String root_leaf = nodes[i];
			// get cases - root node's leaves nodes.
			ArrayList<Node> cases = log.getChildNodes(root_leaf);
			// iterate cases and get his leaves nodes'object.
			for (Iterator<Node> ii = cases.iterator(); ii.hasNext();) {
				// get each event - cases' leaves nodes object.
				Node case_ = ii.next();
				ArrayList<Node> events = case_.getChildNames_childObjs().get(
						"Event");
				for (Iterator<Node> iii = events.iterator(); iii.hasNext();) {
					Node event = iii.next();
					// get actor, receivers - event's leaves nodes.
					ArrayList<Node> actors = event.getChildNames_childObjs()
							.get("Actor");

					ArrayList<Node> performative = event
							.getChildNames_childObjs().get("Performative");
					String performativeToString = performative.get(0).getID()
							.toLowerCase();
					ArrayList<Node> taskss = event.getChildNames_childObjs()
							.get("Task");
					// execute
					if (EXECUTE.contains(performativeToString)) {
						String taskID = taskss.get(0).getID().toLowerCase();
						String actorID = actors.get(0).getID().toLowerCase();
						int indexOfTask = tasks.indexOf(taskID);
						int indexOfActor = agents.indexOf(actorID);
						activityAgentNetMatrix[indexOfActor][indexOfTask] = 1;
					}
				}
			}
		}

		// Test
		System.out.println("************Test 1*************");
		for (int i = 0; i < tasks.size(); i++) {
			System.out.print(tasks.get(i) + "/");
		}

		System.out.println();
		for (int i = 0; i < agents.size(); i++) {
			System.out.print(agents.get(i) + "/");
		}
		System.out.println();
		// for (int i = 0; i < agentAmount; i++) {
		// for (int j = 0; j < taskAmount; j++) {
		// System.out.print(activityAgentNetMatrix[i][j] + "  ");
		// }
		// System.out.println();
		// }
		return activityAgentNetMatrix;
	}

	private static int getAgentAmount(LogFile log) {
		int agentAmount = 0;
		String[] nodes = log.getChildNodeNames();
		// Get leaves nodes of root node.
		for (int i = 0; i < nodes.length; i++) {
			// name of root node's leaves nodes.
			String root_leaf = nodes[i];
			// get cases - root node's leaves nodes.
			ArrayList<Node> cases = log.getChildNodes(root_leaf);
			// iterate cases and get his leaves nodes'object.
			for (Iterator<Node> ii = cases.iterator(); ii.hasNext();) {
				// get each event - cases' leaves nodes object.
				Node case_ = ii.next();
				ArrayList<Node> events = case_.getChildNames_childObjs().get(
						"Event");
				for (Iterator<Node> iii = events.iterator(); iii.hasNext();) {
					Node event = iii.next();
					// get actor, receivers - event's leaves nodes.
					ArrayList<Node> actors = event.getChildNames_childObjs()
							.get("Actor");
					ArrayList<Node> receiverss = event
							.getChildNames_childObjs().get("Receivers");
					// The collection (agents) of actor and receivers is empty
					// or
					// not
					String actorID = actors.get(0).getID().toLowerCase();
					if (agents.isEmpty()) {
						// add actor to the collection
						if (!actorID.equalsIgnoreCase("System"))
							agents.add(actorID.toLowerCase());
					} else {
						if (!agents.contains(actorID)) {
							if (!actorID.equalsIgnoreCase("System"))
								agents.add(actorID.toLowerCase());
						}
					}
					// add each receiver to the collection
					ArrayList<Node> receivers = receiverss.get(0)
							.getChildNames_childObjs().get("Receiver");
					for (Iterator<Node> iiii = receivers.iterator(); iiii
							.hasNext();) {
						Node receiver = iiii.next();
						String receiverName = receiver.getID().toLowerCase();
						if (!agents.contains(receiverName)) {
							if (!receiverName.equalsIgnoreCase("System"))
								agents.add(receiverName);
						}
					}
				}
			}
		}
		// create a matrix and the size of matrix is amount of agent * amount of
		// agent.
		agentAmount = agents.size();
		return agentAmount;
	}

	private static int getTaskAmount(LogFile log) {
		int taskAmount = 0;
		String[] nodes = log.getChildNodeNames();
		// Get leaves nodes of root node.
		for (int i = 0; i < nodes.length; i++) {
			// name of root node's leaves nodes.
			String root_leaf = nodes[i];
			// get cases - root node's leaves nodes.
			ArrayList<Node> cases = log.getChildNodes(root_leaf);
			// iterate cases and get his leaves nodes'object.
			for (Iterator<Node> ii = cases.iterator(); ii.hasNext();) {
				// get each event - cases' leaves nodes object.
				Node case_ = ii.next();
				ArrayList<Node> events = case_.getChildNames_childObjs().get(
						"Event");
				for (Iterator<Node> iii = events.iterator(); iii.hasNext();) {
					Node event = iii.next();
					// get actor, receivers - event's leaves nodes.
					ArrayList<Node> taskss = event.getChildNames_childObjs()
							.get("Task");
					// The collection (agents) of actor and receivers is empty
					// or not
					ArrayList<Node> performative = event
							.getChildNames_childObjs().get("Performative");
					String performativeToString = performative.get(0).getID()
							.toLowerCase();

					if (EXECUTE.contains(performativeToString)) {
						String taskID = taskss.get(0).getID().toLowerCase();
						if (tasks.isEmpty()) {
							tasks.add(taskID);
						} else {
							if (!tasks.contains(taskID))
								tasks.add(taskID);
						}

					}
				}
			}
		}
		// create a matrix and the size of matrix is amount of agent * amount of
		// agent.
		taskAmount = tasks.size();
		return taskAmount;
	}

	public static void createFileVNA(Integer[][] matrix, String filePath) {
		File pointVNA = new File(filePath);
		try {
			FileWriter fw = new FileWriter(pointVNA);
			BufferedWriter bw = new BufferedWriter(fw);
			bw.write("*Node data" + "\n");
			bw.write("*Node properties" + "\n");
			bw.write("*Tie data" + "\n");
			bw.write("AGENT_A AGENT_B \"" + "Agents' realising same activities"
					+ "\"" + "\n");
			for (int i = 0; i < matrix.length; i++) {
				for (int j = 0; j < matrix.length; j++) {
					if (matrix[i][j] != 0) {
						String actor = agents.get(i);
						String receiver = agents.get(j);
						bw.write("\"" + actor + "\"");
						bw.write(" ");
						bw.write("\"" + receiver + "\"");
						bw.write(" ");
						bw.write("" + matrix[i][j] + "");
						bw.write("\n");
					}
				}
			}
			bw.flush();
			bw.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static void createBatchFile(String filePath, String vnaName) {
		File pointBatch = new File(filePath);
//		String nameOfFile = "";
//		if (filePath.contains("/")) {
//			StringTokenizer st = new StringTokenizer(filePath, "/");
//
//			while (st.hasMoreTokens()) {
//				nameOfFile = st.nextToken();
//			}
//		} else if (filePath.contains("\\")) {
//			StringTokenizer st = new StringTokenizer(filePath, "\\");
//			while (st.hasMoreTokens()) {
//				nameOfFile = st.nextToken();
//			}
//		}

		try {
			FileWriter fw = new FileWriter(pointBatch);
			BufferedWriter bw = new BufferedWriter(fw);
			bw.write("Loadvna " + vnaName + "\n");
			bw.write("runlayout" + "\n");
			bw.flush();
			bw.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
